# +----------------------------------------------------------------------
# | Pink [ A modern python web framework ]
# +----------------------------------------------------------------------
# | Copyright (c) 2023 http:#unnnnn.com All rights reserved.
# +----------------------------------------------------------------------
# | Author: chenjianhua <unnnnn@foxmail.com>
# +----------------------------------------------------------------------

from inspect import isclass

from .Provider import Provider
from ..exceptions import RouteNotFoundException
from ..facades import Response as ResponseFacade
from ..pipeline import Pipeline
from ..routes import Route
from ..routes.commands import RouteListCommand


class RouteProvider(Provider):
    def __init__(self, application):
        self.application = application

    def register(self):
        Route.set_controller_locations(self.application.make("controllers.location"))
        self.application.make("commands").add(RouteListCommand(self.application))

    def boot(self):
        from ..response import Response

        router = self.application.make("router")
        request = self.application.make("request")
        response = self.application.make("response")

        route = router.find(
            request.get_path(), request.get_request_method(), request.get_subdomain()
        )
        if not route:
            raise RouteNotFoundException(
                f"{request.get_request_method()} {request.get_path()} : 404 Not Found"
            )

        request.route = route

        # Run before middleware
        before_middleware = Pipeline(request, response).through(
            self.application.make("middleware").get_http_middleware(),
            handler="before",
        )

        exception = None
        if before_middleware:
            request.load_params(route.extract_parameters(request.get_path()))
            route_middleware = self.application.make("middleware").run_route_middleware(
                route.get_middlewares(), request, response, callback="before"
            )

            if route_middleware:
                try:
                    data = route.get_response(self.application)
                    if isinstance(data, Response) or (
                        isclass(data) and issubclass(data, ResponseFacade)
                    ):
                        pass
                    else:
                        response.view(data)
                except Exception as e:
                    exception = e

                self.application.make("middleware").run_route_middleware(
                    route.get_middlewares(), request, response, callback="after"
                )

        Pipeline(request, response).through(
            self.application.make("middleware").get_http_middleware(),
            handler="after",
        )

        if exception:
            raise exception
